package config

import (
	"fmt"
	"time"

	"octopus/hextech/core"
	"octopus/hextech/db"
	"octopus/hextech/nlog"
	cache "octopus/hextech/redis"
	"octopus/hextech/server/env"

	"github.com/go-redis/redis/v7"
	"gorm.io/gorm"
)

type Options struct {
	ComponentConfig Config
	WebServer       *core.WebServer
	RpcXServer      *core.RpcXServer
	Db              *gorm.DB
	Redis           *redis.Client
}

func NewOptions(configName string, configPath string) (*Options, error) {
	InitConfig(configName, configPath)
	return &Options{
		ComponentConfig: Get(),
	}, nil
}

// Complete completes all the required options
func (o *Options) Complete() error {
	if err := o.register(); err != nil {
		return err
	}
	return nil
}

func (o *Options) register() error {
	// register env
	if err := o.registerEnv(); err != nil {

	}
	// 注册日志
	if err := o.registerLogger(); err != nil {
		fmt.Printf("[REGISTER] register logger failed, err: %v\n", err.Error())
		return err
	}

	// 注册数据库
	if err := o.registerDatabase(); err != nil {
		fmt.Printf("[REGISTER] register db failed, err: %v\n", err.Error())
		return err
	}

	// 注册Redis
	if err := o.registerRedis(); err != nil {
		fmt.Printf("[REGISTER] register redis failed, err: %v\n", err.Error())
		return err
	}

	// 注册web服务器
	if err := o.registerWebServer(); err != nil {
		fmt.Printf("[REGISTER] register web server failed, err: %v\n", err.Error())
		return err
	}

	// 注册rpc服务
	if err := o.registerRpcXServer(); err != nil {
		fmt.Printf("[REGISTER] register rpc server failed, err: %v\n", err.Error())
		return err
	}

	// 注册clusterSets
	//if err := o.registerK8s(); err != nil {
	//	fmt.Printf("[REGISTER] register k8s failed, err: %v\n", err)
	//	return err
	//}
	//fmt.Println("[REGISTER] register k8s successful")
	return nil
}

// Close 关闭服务和资源
func (o *Options) Close() {
	// 关闭数据库
	if o.Db != nil {
		d, _ := o.Db.DB()
		_ = d.Close()
	}
	// 关闭redis
	if o.Redis != nil {
		_ = o.Redis.Close()
	}
	// 关闭http服务
	if o.WebServer != nil {
		o.WebServer.Close()
	}
	// 关闭rpc服务
	if o.RpcXServer != nil {
		o.RpcXServer.Close()
	}
}

// RunServer 启动服务
func (o *Options) RunServer() {
	// 启动http服务
	if o.WebServer != nil {
		o.WebServer.Run()
	}

	// 启动rpc服务
	if o.RpcXServer != nil {
		o.RpcXServer.Run()
	}
}

func (o *Options) registerEnv() error {
	env.SetAppName(o.ComponentConfig.APP.Name)
	return nil
}

func (o *Options) registerLogger() error {
	logConf := o.ComponentConfig.Log
	logOptions := nlog.LogConfig{
		Level:   logConf.Level,
		Stdout:  logConf.Stdout,
		LogRate: logConf.LogRate,
		LogRateConf: nlog.LogRateConf{
			MaxAge:     logConf.LogRateConf.MaxAge,
			MaxBackups: logConf.LogRateConf.MaxBackups,
			MaxSize:    logConf.LogRateConf.MaxSize,
		},
	}
	nlog.InitLog(logOptions)
	fmt.Println("[REGISTER] register logger successful")
	return nil
}

func (o *Options) registerDatabase() (err error) {
	dbConf := o.ComponentConfig.Mysql
	dbOptions := &db.MySQLOptions{
		Host:                  dbConf.Addr,
		Username:              dbConf.User,
		Password:              dbConf.Password,
		Port:                  dbConf.Port,
		Database:              dbConf.Database,
		MaxIdleConnections:    dbConf.MaxIdleConn,
		MaxOpenConnections:    dbConf.MaxOpenConn,
		MaxConnectionLifeTime: dbConf.ConnMaxLifeTime,
		LogLevel:              dbConf.LogLevel,
	}

	o.Db, err = db.NewMySQL(dbOptions)
	if err != nil {
		return err
	}
	fmt.Println("[REGISTER] register db successful")
	return nil
}

func (o *Options) registerWebServer() error {
	conf := o.ComponentConfig.HTTPServer
	webServerOptions := &core.WebServerOptions{
		Mode:       conf.Mode,
		Address:    conf.Address,
		Port:       conf.Port,
		RouterFunc: nil, // 注册时无值，Set进去
	}
	webServer, err := core.NewWebServer(
		webServerOptions,
	)
	if err != nil {
		return err
	}
	o.WebServer = webServer
	fmt.Println("[REGISTER] register web server successful")
	return nil
}

func (o *Options) registerRedis() error {
	redisConf := o.ComponentConfig.Redis
	redisOpt := &cache.Options{
		Addr:       redisConf.Addr,
		Port:       redisConf.Port,
		Db:         redisConf.Db,
		MaxReTries: redisConf.MaxReTries,
		Password:   redisConf.Password,
		PoolSize:   redisConf.PoolSize,
	}
	client, err := cache.New(redisOpt)
	if err != nil {
		return err
	}
	o.Redis = client
	fmt.Println("[REGISTER] register redis successful")
	return nil
}

func (o *Options) registerRpcXServer() error {
	conf := o.ComponentConfig.RpcXServer
	var poolConf *core.RpcXServerOptionsPoolConfig
	if conf.PondPoolMaxWorkers > 0 && conf.PondPoolMaxCapacity > 0 {
		poolConf = &core.RpcXServerOptionsPoolConfig{
			MaxWorkers:  conf.PondPoolMaxWorkers,
			MaxCapacity: conf.PondPoolMaxCapacity,
		}
	}
	rpcConf := &core.RpcXServerConfig{
		Base: &core.RpcXServerBaseConfig{
			Port:       conf.Port,
			Address:    conf.Address,
			ServerName: conf.ServerName,
			CertFile:   conf.CertFile,
			KeyFile:    conf.KeyFile,
		},
		Options: &core.RpcXServerOptionsConfig{
			ReadTimeout:        time.Duration(conf.ReadTimeout) * time.Millisecond,
			WriteTimeout:       time.Duration(conf.WriteTimeout) * time.Millisecond,
			Pool:               poolConf,
			CustomPool:         nil,
			AsyncWrite:         false,
			TCPKeepAlivePeriod: 0,
		},
		Etcd: &core.RpcXServerEtcdConfig{
			Nodes:          conf.EtcdNodes,
			BasePath:       conf.EtcdBasePath,
			UpdateInterval: time.Duration(conf.EtcdUpdateInterval) * time.Second,
			Expired:        time.Duration(conf.EtcdExpired) * time.Second,
		},
	}
	srv, err := core.NewRpcXServer(
		rpcConf,
	)
	if err != nil {
		return err
	}
	o.RpcXServer = srv
	fmt.Println("[REGISTER] register rpc server successful")
	return nil
}
